import Foundation
import ProgressHUD

protocol WXApiManagerDelegate: AnyObject {
    func managerDidRecvMessageResponse(_ response: SendMessageToWXResp)
    func managerDidRecvAuthResponse(_ response: SendAuthResp)
    func managerDidRecvAddCardResponse(_ response: AddCardToWXCardPackageResp)
    func managerDidRecvChooseCardResponse(_ response: WXChooseCardResp)
    func managerDidRecvChooseInvoiceResponse(_ response: WXChooseInvoiceResp)
    func managerDidRecvSubscribeMsgResponse(_ response: WXSubscribeMsgResp)
    func managerDidRecvLaunchMiniProgram(_ response: WXLaunchMiniProgramResp)
    func managerDidRecvInvoiceAuthInsertResponse(_ response: WXInvoiceAuthInsertResp)
//    func managerDidRecvNonTaxpayResponse(_ response: WXNontaxPayResp)
//    func managerDidRecvPayInsuranceResponse(_ response: WXPayInsuranceResp)
    func managerDidRecvShowMessageReq(_ request: ShowMessageFromWXReq)
    func managerDidRecvLaunchFromWXReq(_ request: LaunchFromWXReq)
}

class WXApiManager: NSObject, WXApiDelegate {
    static let shared = WXApiManager()
    
    weak var delegate: WXApiManagerDelegate?
    
    private override init() {
        super.init()
    }
    
    func onResp(_ resp: BaseResp) {
        switch resp {
        case let messageResp as SendMessageToWXResp:
            delegate?.managerDidRecvMessageResponse(messageResp)
        case let authResp as SendAuthResp:
            delegate?.managerDidRecvAuthResponse(authResp)
        case let addCardResp as AddCardToWXCardPackageResp:
            delegate?.managerDidRecvAddCardResponse(addCardResp)
        case let chooseCardResp as WXChooseCardResp:
            delegate?.managerDidRecvChooseCardResponse(chooseCardResp)
        case let chooseInvoiceResp as WXChooseInvoiceResp:
            delegate?.managerDidRecvChooseInvoiceResponse(chooseInvoiceResp)
        case let subscribeMsgResp as WXSubscribeMsgResp:
            delegate?.managerDidRecvSubscribeMsgResponse(subscribeMsgResp)
        case let launchMiniProgramResp as WXLaunchMiniProgramResp:
            delegate?.managerDidRecvLaunchMiniProgram(launchMiniProgramResp)
        case let invoiceAuthInsertResp as WXInvoiceAuthInsertResp:
            delegate?.managerDidRecvInvoiceAuthInsertResponse(invoiceAuthInsertResp)
//        case let nonTaxPayResp as WXNontaxPayResp:
//            delegate?.managerDidRecvNonTaxpayResponse(nonTaxPayResp)
//        case let payInsuranceResp as WXPayInsuranceResp:
//            delegate?.managerDidRecvPayInsuranceResponse(payInsuranceResp)
        default:
            break
        }
        
       
    }
    
    func onReq(_ req: BaseReq) {
        switch req {
        case let showMessageReq as ShowMessageFromWXReq:
            delegate?.managerDidRecvShowMessageReq(showMessageReq)
        case let launchReq as LaunchFromWXReq:
            delegate?.managerDidRecvLaunchFromWXReq(launchReq)
        default:
            break
        }
    }
    
//    func onNeedGrantReadPasteBoardPermission(with openURL: URL, completion: @escaping WXGrantReadPasteBoardPermissionCompletion) {
//        print("onNeedGrantReadPasteBoardPermission:\(openURL.absoluteString)")
//        completion()
//    }
}

struct WXShareModel: Codable {
    var text: String?
    let imagePath: String?
    let entranceMiniProgramUsername: String?
    let entranceMiniProgramPath: String?
    let webpageUrl: String?
    let miniprogramType: Int?
    let withShareTicket: String?
    
    init(text: String? = nil, imagePath: String?, entranceMiniProgramUsername: String?, entranceMiniProgramPath: String?, webpageUrl: String?, miniprogramType: Int?, withShareTicket: String?) {
        if let rawText = text,
           !rawText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty  {
            self.text = rawText
        } else {
            self.text = "爆单键盘"
        }
        self.imagePath = imagePath
        self.entranceMiniProgramUsername = entranceMiniProgramUsername
        self.entranceMiniProgramPath = entranceMiniProgramPath
        self.webpageUrl = webpageUrl
        self.miniprogramType = miniprogramType
        self.withShareTicket = withShareTicket
    }
    
    enum CodingKeys: String, CodingKey {
        case text
        case imagePath
        case entranceMiniProgramUsername
        case entranceMiniProgramPath
        case webpageUrl
        case miniprogramType
        case withShareTicket
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 核心：text 为空字符串时也赋默认值
        if let rawText = try container.decodeIfPresent(String.self,forKey: .text),
           !rawText.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
            text = rawText
        } else {
            text = "爆单键盘"
        }
        imagePath = try container.decodeIfPresent(String.self, forKey: .imagePath)
        entranceMiniProgramUsername = try container.decodeIfPresent(String.self, forKey: .entranceMiniProgramUsername)
        entranceMiniProgramPath = try container.decodeIfPresent(String.self, forKey: .entranceMiniProgramPath)
        webpageUrl = try container.decodeIfPresent(String.self, forKey: .webpageUrl)
        if let intValue = try? container.decodeIfPresent(Int.self, forKey: .miniprogramType) {
            miniprogramType = intValue
        } else if let stringValue = try? container.decodeIfPresent(String.self, forKey: .miniprogramType),
                  let intFromString = Int(stringValue) {
            miniprogramType = intFromString
        } else {
            miniprogramType = nil
        }
        withShareTicket = try container.decodeIfPresent(String.self, forKey: .withShareTicket)
    }

}

extension WXApi {
    
    static func shareAction(share: WXShareModel) {
        DispatchQueue.main.async {
            ProgressHUD.animate("调用微信分享...", interaction: false)
        }
        guard let path = share.imagePath,
              let url = URL(string: path) else {
           
            proceedToShare(share: share, imageData: nil)
            return
        }
        print("图片地址:\(url)")
        let request = URLRequest(url: url)
        URLSession.shared.dataTask(with: request) { (imageData, response, error) in
            guard let imageData = imageData, error == nil else {
                proceedToShare(share: share, imageData: nil)
                return
            }

            guard let image = UIImage(data: imageData) else {
                proceedToShare(share: share, imageData: nil)
                return
            }

            // 图片
            guard (share.entranceMiniProgramUsername != nil)  else {
                proceedToShare(share: share, imageData: imageData)
                return
            }
            // 小程序-要缩放图片大小
            // 固定目标尺寸
            let targetSize = CGSize(width: 400, height: 320)

            // 计算等比缩放后的高度
            let scale = targetSize.width / image.size.width
            let scaledHeight = image.size.height * scale

            // 图片在新画布中的绘图区域，从顶部开始裁剪到底部（若高度超出）
            let drawRect = CGRect(
                x: 0,
                y: 0,
                width: targetSize.width,
                height: scaledHeight
            )

            // 用 UIGraphicsImageRenderer 画图
            let renderer = UIGraphicsImageRenderer(size: targetSize)
            let croppedImage = renderer.image { _ in
                image.draw(in: drawRect)
            }

            // 尝试压缩成 <128KB
            var finalImageData: Data?
            var compression: CGFloat = 1.0

            while compression > 0 {
                if let data = croppedImage.jpegData(compressionQuality: compression),
                   data.count < 128 * 1024 {
                    finalImageData = data
                    print("最终的大小：\(data.count)")
                    break
                }
                compression -= 0.05
            }

            proceedToShare(share: share, imageData: finalImageData)
        }.resume()
    }
    
    private static func proceedToShare(share: WXShareModel, imageData: Data?) {
        var imageObject: WXImageObject? = nil
        
        var miniProgramObject: WXMiniProgramObject? = nil
        
        if  let name = share.entranceMiniProgramUsername,
        let path = share.entranceMiniProgramPath {
            if (miniProgramObject == nil) {
                miniProgramObject = WXMiniProgramObject()
            }
            miniProgramObject?.webpageUrl = share.webpageUrl ?? "https://www.zmeng123.com"
            miniProgramObject!.userName = name
            miniProgramObject!.path = path
            miniProgramObject?.withShareTicket = share.withShareTicket == "true"
            miniProgramObject?.miniProgramType = WXMiniProgramType(rawValue: UInt(share.miniprogramType!))!
        } else {
            imageObject = WXImageObject()
        }
        
        if let imageData = imageData {
            if miniProgramObject != nil {
                miniProgramObject?.hdImageData = imageData
            } else {
                imageObject!.imageData = imageData
            }
        }
        
        var message: WXMediaMessage? = nil
        
        if (imageObject != nil) || (miniProgramObject != nil) {
            message = WXMediaMessage()
            message!.mediaObject = miniProgramObject ?? imageObject as Any
            message?.thumbData = nil
            if let text = share.text {
                message!.title = text
                message!.description = text
            }
        }
            
        let req = SendMessageToWXReq()
        if message != nil {
            req.bText = false
            req.message = message!
        } else {
            req.bText = true
            req.text = share.text!
        }
        req.scene = 0
        // 1. 尝试提前写入剪切板失败：过早会被微信覆盖，过晚会在微信里吊不起分享的页面
        UIPasteboard.general.string = share.text!
//        print("剪切板数据：\(String(describing: UIPasteboard.general.string))")
        DispatchQueue.main.async {
            WXApi.send(req) { success in
                // 调用是否成功
                if !success {
                    ProgressHUD.failed("调用微信分享失败！")
                } else {
                    ProgressHUD.dismiss()
                    // 2. 尝试延迟写入剪切板-失败：app切换到后台以后会写入失败
//                    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
//                        print("要分享的：\(share.text!)")
//                        UIPasteboard.general.string = share.text!
//                        // 马上读取回剪切板，验证是否设置成功
//                        if UIPasteboard.general.string == share.text! {
//                            print("✅ 成功写入剪切板")
//                        } else {
//                            print("❌ 写入剪切板失败")
//                        }
//                    }
                }
            }
        }
    }
 }

